﻿using CaseManagerLibrary.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Windows.Forms;

namespace CaseManagerLibrary.Http
{
    public static class HttpHelper
    {
        private static readonly Encoding DEFAULTENCODE = Encoding.UTF8;

        public static CookieContainer cookies = new CookieContainer();
        public static NameValueCollection headers = new NameValueCollection();

        /// <summary>
        /// HttpUploadFile
        /// </summary>
        /// <param name="url"></param>
        /// <param name="file"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string HttpUploadFile(string url, string file, NameValueCollection data)
        {
            return HttpUploadFile(url, file, data, DEFAULTENCODE);
        }

        /// <summary>
        /// HttpUploadFile
        /// </summary>
        /// <param name="url"></param>
        /// <param name="file"></param>
        /// <param name="data"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string HttpUploadFile(string url, string file, NameValueCollection data, Encoding encoding)
        {
            return HttpUploadFile(url, new string[] { file }, data, encoding);
        }

        /// <summary>
        /// HttpUploadFile
        /// </summary>
        /// <param name="url"></param>
        /// <param name="files"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string HttpUploadFile(string url, string[] files, NameValueCollection data)
        {
            return HttpUploadFile(url, files, data, DEFAULTENCODE);
        }

        /// <summary>
        /// HttpUploadFile
        /// </summary>
        /// <param name="url"></param>
        /// <param name="files"></param>
        /// <param name="data"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string HttpUploadFile(string url, string[] files, NameValueCollection data, Encoding encoding)
        {
            string result = "";

            try
            {

                string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
                byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
                byte[] endbytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");

                //1.HttpWebRequest
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.ContentType = "multipart/form-data; boundary=" + boundary;
                request.Method = "POST";
                request.KeepAlive = true;
                request.Credentials = CredentialCache.DefaultCredentials;
                request.CookieContainer = cookies;
                request.Headers.Add(headers);
                request.KeepAlive = true;
                using (Stream stream = request.GetRequestStream())
                {
                    //1.1 key/value
                    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
                    if (data != null)
                    {
                        foreach (string key in data.Keys)
                        {
                            stream.Write(boundarybytes, 0, boundarybytes.Length);
                            string formitem = string.Format(formdataTemplate, key, data[key]);
                            byte[] formitembytes = encoding.GetBytes(formitem);
                            stream.Write(formitembytes, 0, formitembytes.Length);
                        }
                    }

                    //1.2 file
                    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
                    byte[] buffer = new byte[4096];
                    int bytesRead = 0;
                    for (int i = 0; i < files.Length; i++)
                    {
                        stream.Write(boundarybytes, 0, boundarybytes.Length);
                        string header = string.Format(headerTemplate, "file" + i, Path.GetFileName(files[i]));
                        byte[] headerbytes = encoding.GetBytes(header);
                        stream.Write(headerbytes, 0, headerbytes.Length);
                        using (FileStream fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
                        {
                            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                            {
                                stream.Write(buffer, 0, bytesRead);
                            }

                            fileStream.Close();
                        }
                    }

                    //1.3 form end
                    stream.Write(endbytes, 0, endbytes.Length);
                    stream.Close();
                }
                //2.WebResponse


                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    result = stream.ReadToEnd();
                    stream.Close();
                }
            }
            catch { }

            return result;
        }

        private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受   
        }

        public static string PostLogin(string url, IDictionary<string, string> parameters, Encoding charset)
        {
            string result = "";
            try
            {
                HttpWebRequest request = null;
                //HTTPSQ请求
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.UserAgent = DefaultUserAgent;
                request.CookieContainer = new CookieContainer();
                request.KeepAlive = true;
                //如果需要POST数据   
                if (!(parameters == null || parameters.Count == 0))
                {
                    StringBuilder buffer = new StringBuilder();
                    int i = 0;
                    foreach (string key in parameters.Keys)
                    {
                        if (i > 0)
                        {
                            buffer.AppendFormat("&{0}={1}", key, parameters[key]);
                        }
                        else
                        {
                            buffer.AppendFormat("{0}={1}", key, parameters[key]);
                        }
                        i++;
                    }
                    byte[] data = charset.GetBytes(buffer.ToString());
                    using (Stream stream = request.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);
                    }
                }

                // return request.GetResponse() as HttpWebResponse;

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    result = stream.ReadToEnd();
                }

                cookies.Add(response.Cookies);
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);

                result = JsonConvert.SerializeObject(new HResult() { success = false, message = ex.Message });
            }

            return result;
        }

        public static string Post(string url, IDictionary<string, string> parameters, Encoding charset)
        {
            string result = "";
            try
            {
                HttpWebRequest request = null;
                //HTTPSQ请求
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.UserAgent = DefaultUserAgent;
                request.CookieContainer = cookies;
                request.Headers.Add(headers);
                request.KeepAlive = true;
                //如果需要POST数据   
                if (!(parameters == null || parameters.Count == 0))
                {
                    StringBuilder buffer = new StringBuilder();
                    int i = 0;
                    foreach (string key in parameters.Keys)
                    {
                        if (i > 0)
                        {
                            buffer.AppendFormat("&{0}={1}", key, parameters[key]);
                        }
                        else
                        {
                            buffer.AppendFormat("{0}={1}", key, parameters[key]);
                        }
                        i++;
                    }
                    byte[] data = charset.GetBytes(buffer.ToString());
                    using (Stream stream = request.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);
                    }
                }

                HttpWebResponse response = null;

                response = (HttpWebResponse)request.GetResponse();

                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    result = stream.ReadToEnd();
                }

            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                result = JsonConvert.SerializeObject(new HResult() { success = false, message = ex.Message });
            }

            return result;

        }

        public static string Post(string url, IDictionary<string, string> parameters)
        {
            return Post(url, parameters, DEFAULTENCODE);
        }

        public static TResult Post<TResult>(string url, IDictionary<string, string> parameters)
        {
            string response = Post(url, parameters, DEFAULTENCODE);

            return JsonConvert.DeserializeObject<TResult>(response);
        }

        public static string Post(string url, string json, Encoding charset)
        {
            string result = "";
            try
            {
                HttpWebRequest request = null;
                //HTTPSQ请求
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
                request.Method = "POST";
                request.ContentType = "application/json";
                request.UserAgent = DefaultUserAgent;
                request.CookieContainer = cookies;
                request.Headers.Add(headers);
                request.KeepAlive = true;

                //如果需要POST数据   
                if (!string.IsNullOrEmpty(json))
                {
                    byte[] data = charset.GetBytes(json);
                    using (Stream stream = request.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);
                    }
                }

                HttpWebResponse response = null;

                response = (HttpWebResponse)request.GetResponse();

                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    result = stream.ReadToEnd();
                }

            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                result = JsonConvert.SerializeObject(new HResult() { success = false, message = ex.Message });
            }

            return result;
        }

        public static string Post(string url, string json)
        {
            return Post(url, json, DEFAULTENCODE);
        }

        public static TResult Post<TResult>(string url, string json)
        {
            string response = Post(url, json, DEFAULTENCODE);

            return JsonConvert.DeserializeObject<TResult>(response);
        }

        /// <summary>  
        /// 创建GET方式的HTTP请求  
        /// </summary>  
        /// <param name="url">请求的URL</param>  
        /// <param name="timeout">请求的超时时间</param>  
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>  
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>  
        /// <returns></returns>  
        public static string Get(string url, int? timeout, string userAgent)
        {
            string result = "";
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                request.Method = "GET";
                request.UserAgent = DefaultUserAgent;
                if (!string.IsNullOrEmpty(userAgent))
                {
                    request.UserAgent = userAgent;
                }
                if (timeout.HasValue)
                {
                    request.Timeout = timeout.Value;
                }
                request.CookieContainer = cookies;
                request.Headers.Add(headers);
                request.KeepAlive = true;

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                {
                    result = stream.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);

                result = JsonConvert.SerializeObject(new HResult() { success = false, message = ex.Message });
            }

            return result;
        }

        public static string Get(string url)
        {
            return Get(url, null, null);
        }

        public static TResult Get<TResult>(string url)
        {
            string response = Get(url, null, null);

            return JsonConvert.DeserializeObject<TResult>(response);
        }

        public static HResult HttpDownload(string url, string filePath)
        {
            HResult result = new HResult();

            try
            {
                HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
                request.CookieContainer = cookies;
                request.Headers.Add(headers);
                request.KeepAlive = true;

                HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                if (response.ContentType == "application/octet-stream")
                {
                    Stream st = response.GetResponseStream();
                    Stream so = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
                    byte[] by = new byte[1024];
                    int osize = st.Read(by, 0, (int)by.Length);
                    while (osize > 0)
                    {
                        so.Write(by, 0, osize);
                        osize = st.Read(by, 0, (int)by.Length);
                    }
                    so.Close();
                    st.Close();
                    response.Close();
                    request.Abort();

                    result.success = true;
                }
                else
                {
                    result.success = false;
                    using (StreamReader stream = new StreamReader(response.GetResponseStream()))
                    {
                        result.message = stream.ReadToEnd();
                    }
                }
            }
            catch (System.Exception e)
            {
                result.success =  false;
                result.message = e.Message + (e.InnerException != null ? e.InnerException.Message : "");
            }

            return result;
        }
    }
}
